package system

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/flipped-aurora/gin-vue-admin/server/model/im/request"
	"github.com/flipped-aurora/gin-vue-admin/server/service/im"
	"strconv"
	"strings"
	"time"

	"github.com/flipped-aurora/gin-vue-admin/server/model/common"
	systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
	systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"

	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
	"github.com/flipped-aurora/gin-vue-admin/server/utils"
	"github.com/google/uuid"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"math/rand"
)

//@author: [piexlmax](https://github.com/piexlmax)
//@function: Register
//@description: 用户注册
//@param: u model.SysUser
//@return: userInter system.SysUser, err error

type UserService struct{}

var UserServiceApp = new(UserService)

func (userService *UserService) Register(u system.SysUser) (userInter system.SysUser, err error) {
	var user system.SysUser
	var errorDetails []string

	// 检查用户名是否已注册
	if !errors.Is(global.GVA_DB.Where("username = ?", u.Username).First(&user).Error, gorm.ErrRecordNotFound) {
		errorDetails = append(errorDetails, "用户名已注册")
	}

	// 检查手机号是否已注册（如果提供了手机号）
	if u.Phone != "" {
		if !errors.Is(global.GVA_DB.Where("phone = ?", u.Phone).First(&user).Error, gorm.ErrRecordNotFound) {
			errorDetails = append(errorDetails, "手机号已注册")
		}
	}

	// 检查邮箱是否已注册（如果提供了邮箱）
	if u.Email != "" {
		if !errors.Is(global.GVA_DB.Where("email = ?", u.Email).First(&user).Error, gorm.ErrRecordNotFound) {
			errorDetails = append(errorDetails, "邮箱已注册")
		}
	}

	// 如果有错误，返回详细的错误信息
	if len(errorDetails) > 0 {
		errorMsg := "注册失败："
		for i, detail := range errorDetails {
			if i > 0 {
				errorMsg += "，"
			}
			errorMsg += detail
		}
		return userInter, errors.New(errorMsg)
	}

	// 附加uuid 密码hash加密 注册
	u.Password = utils.BcryptHash(u.Password)
	u.UUID = uuid.New()
	err = global.GVA_DB.Create(&u).Error
	if err != nil {
		// 数据库创建失败时的详细错误信息
		if strings.Contains(err.Error(), "Duplicate entry") {
			if strings.Contains(err.Error(), "username") {
				return userInter, errors.New("注册失败：用户名已存在")
			} else if strings.Contains(err.Error(), "phone") {
				return userInter, errors.New("注册失败：手机号已存在")
			} else if strings.Contains(err.Error(), "email") {
				return userInter, errors.New("注册失败：邮箱已存在")
			}
		}
		return userInter, fmt.Errorf("注册失败：数据库错误 - %v", err)
	}

	// 同步用户信息到im模块
	var imUser = request.IMUser{
		UserID:   strconv.FormatUint(uint64(u.ID), 10),
		NickName: u.NickName,
		FaceURL:  u.HeaderImg,
	}
	errRegister := im.IMUserServiceApp.RegisterUsers(context.Background(), []request.IMUser{imUser})
	if errRegister != nil {
		return u, errRegister
	}
	return u, err
}

// @author: [piexlmax](https://github.com/piexlmax)
// @function: WxOneTapRegister
// @description: 微信一键注册登录
// @param: openid, phone string
// @return: user *system.SysUser, err error
func (userService *UserService) WxOneTapRegister(openid, phone string) (user *system.SysUser, err error) {
	// 开启事务
	tx := global.GVA_DB.Begin()
	if tx.Error != nil {
		return nil, tx.Error
	}
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 查询用户是否存在
	var existingUser system.SysUser
	if err := tx.Where("openid = ?", openid).First(&existingUser).Error; err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			tx.Rollback()
			return nil, err
		}

		// 用户不存在，创建新用户
		randomUsername := GenerateRandomUsername(8)
		newUser := system.SysUser{
			Username:  randomUsername,
			NickName:  "微信用户_" + randomUsername,
			Password:  "", // 微信登录无需密码
			Phone:     phone,
			Openid:    &openid,
			HeaderImg: "",
			Enable:    1, // 默认启用
			UUID:      uuid.New(),
		}

		if err := tx.Create(&newUser).Error; err != nil {
			tx.Rollback()
			return nil, err
		}

		// 同步用户信息到im模块
		var imUser = request.IMUser{
			UserID:   strconv.FormatUint(uint64(newUser.ID), 10),
			NickName: newUser.NickName,
			FaceURL:  newUser.HeaderImg,
		}
		errRegister := im.IMUserServiceApp.RegisterUsers(context.Background(), []request.IMUser{imUser})
		if errRegister != nil {
			tx.Rollback()
			return nil, errRegister
		}

		if newUser.Phone == "" {
			global.GVA_LOG.Info("创建新用户成功，未绑定手机号", zap.String("openid", openid), zap.String("username", newUser.Username))
		} else {
			global.GVA_LOG.Info("创建新用户成功，已绑定手机号", zap.String("openid", openid), zap.String("phone", newUser.Phone))
		}

		user = &newUser
	} else {
		// 用户存在，更新手机号（如果为空且提供了新手机号）
		if existingUser.Phone == "" && phone != "" {
			existingUser.Phone = phone
			if err := tx.Save(&existingUser).Error; err != nil {
				tx.Rollback()
				return nil, err
			}
			global.GVA_LOG.Info("更新用户手机号成功", zap.String("openid", openid), zap.String("phone", phone))
		} else if existingUser.Phone != phone && phone != "" {
			global.GVA_LOG.Info("用户已绑定其他手机号，不进行更新", zap.String("openid", openid), zap.String("existingPhone", existingUser.Phone), zap.String("newPhone", phone))
		} else if phone == "" {
			global.GVA_LOG.Info("手机号为空，不更新用户手机号", zap.String("openid", openid), zap.String("existingPhone", existingUser.Phone))
		}
		user = &existingUser
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return nil, err
	}
	return user, nil
}

// GenerateRandomUsername 生成随机8位用户名
func GenerateRandomUsername(length int) string {
	rand.Seed(time.Now().UnixNano())
	letters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

//@author: [piexlmax](https://github.com/piexlmax)
//@author: [SliverHorn](https://github.com/SliverHorn)
//@function: Login
//@description: 用户登录
//@param: u *model.SysUser
//@return: err error, userInter *model.SysUser

func (userService *UserService) Login(u *system.SysUser) (userInter *system.SysUser, err error) {
	if nil == global.GVA_DB {
		return nil, fmt.Errorf("db not init")
	}

	var user system.SysUser
	err = global.GVA_DB.Where("username = ?", u.Username).Preload("Authorities").Preload("Authority").First(&user).Error
	if err == nil {
		if ok := utils.BcryptCheck(u.Password, user.Password); !ok {
			return nil, errors.New("密码错误")
		}
		MenuServiceApp.UserAuthorityDefaultRouter(&user)
	}
	return &user, err
}
func (userService *UserService) CLogin(u *system.SysUser) (userInter *system.SysUser, err error) {
	if nil == global.GVA_DB {
		return nil, fmt.Errorf("db not init")
	}

	var user system.SysUser
	err = global.GVA_DB.Where("phone = ?", u.Phone).First(&user).Error
	if err == nil {
		if ok := utils.BcryptCheck(u.Password, user.Password); !ok {
			return nil, errors.New("密码错误")
		}
	}
	return &user, err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: ChangePassword
//@description: 修改用户密码
//@param: u *model.SysUser, newPassword string
//@return: userInter *model.SysUser,err error

func (userService *UserService) ChangePassword(u *system.SysUser, newPassword string) (userInter *system.SysUser, err error) {
	var user system.SysUser
	if err = global.GVA_DB.Where("id = ?", u.ID).First(&user).Error; err != nil {
		return nil, err
	}
	if ok := utils.BcryptCheck(u.Password, user.Password); !ok {
		return nil, errors.New("原密码错误")
	}
	user.Password = utils.BcryptHash(newPassword)
	err = global.GVA_DB.Save(&user).Error
	return &user, err
}

// GetFollowListIds 滴
func (userService *UserService) GetFollowListIds(userId string, pageNum, pageSize int) (ids []string, total int64, err error) {
	// 查询关注列表
	db := global.GVA_DB.Model(&system.SysUserFollow{})
	db.Where("follower_id = ?", userId)
	limit := pageSize
	offset := pageSize * (pageNum - 1)
	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Limit(limit).Offset(offset).Select("followed_id").Scan(&ids).Error
	return ids, total, err
}
func (userService *UserService) GetFollowedIds(userId string, pageNum, pageSize int) (ids []string, total int64, err error) {
	// 查询被关注列表-粉丝列表
	db := global.GVA_DB.Model(&system.SysUserFollow{})
	db.Where("followed_id", userId)
	limit := pageSize
	offset := (pageNum - 1) * pageSize
	err = db.Count(&total).Error
	if err != nil {
		return nil, total, err
	}
	err = db.Limit(limit).Offset(offset).Select("follower_id").Scan(&ids).Error
	return ids, total, err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: GetUserInfoList
//@description: 分页获取数据
//@param: info request.PageInfo
//@return: err error, list interface{}, total int64

func (userService *UserService) GetUserInfoList(info systemReq.GetUserList) (list interface{}, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	db := global.GVA_DB.Model(&system.SysUser{})
	var userList []system.SysUser
	if info.NickName != "" {
		db = db.Where("nick_name LIKE ?", "%"+info.NickName+"%")
	}
	if info.Phone != "" {
		db = db.Where("phone LIKE ?", "%"+info.Phone+"%")
	}
	if info.Username != "" {
		db = db.Where("username LIKE ?", "%"+info.Username+"%")
	}
	if info.Email != "" {
		db = db.Where("email LIKE ?", "%"+info.Email+"%")
	}
	if info.Grade != 0 {
		db = db.Where("grade = ?", info.Grade)
	}
	if info.School != 0 {
		db = db.Where("school = ?", info.School)
	}
	if info.Major != 0 {
		db = db.Where("major = ?", info.Major)
	}
	if info.Education != 0 {
		db = db.Where("education = ?", info.Education)
	}
	if len(info.UserIds) != 0 {
		db = db.Where("id IN (?)", info.UserIds)
	}

	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Limit(limit).Offset(offset).Preload("Authorities").Preload("Authority").Find(&userList).Error
	return userList, total, err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: SetUserAuthority
//@description: 设置一个用户的权限
//@param: uuid uuid.UUID, authorityId string
//@return: err error

func (userService *UserService) SetUserAuthority(id uint, authorityId uint) (err error) {

	assignErr := global.GVA_DB.Where("sys_user_id = ? AND sys_authority_authority_id = ?", id, authorityId).First(&system.SysUserAuthority{}).Error
	if errors.Is(assignErr, gorm.ErrRecordNotFound) {
		return errors.New("该用户无此角色")
	}

	var authority system.SysAuthority
	err = global.GVA_DB.Where("authority_id = ?", authorityId).First(&authority).Error
	if err != nil {
		return err
	}
	var authorityMenu []system.SysAuthorityMenu
	var authorityMenuIDs []string
	err = global.GVA_DB.Where("sys_authority_authority_id = ?", authorityId).Find(&authorityMenu).Error
	if err != nil {
		return err
	}

	for i := range authorityMenu {
		authorityMenuIDs = append(authorityMenuIDs, authorityMenu[i].MenuId)
	}

	var authorityMenus []system.SysBaseMenu
	err = global.GVA_DB.Preload("Parameters").Where("id in (?)", authorityMenuIDs).Find(&authorityMenus).Error
	if err != nil {
		return err
	}
	hasMenu := false
	for i := range authorityMenus {
		if authorityMenus[i].Name == authority.DefaultRouter {
			hasMenu = true
			break
		}
	}
	if !hasMenu {
		return errors.New("找不到默认路由,无法切换本角色")
	}

	err = global.GVA_DB.Model(&system.SysUser{}).Where("id = ?", id).Update("authority_id", authorityId).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: SetUserAuthorities
//@description: 设置一个用户的权限
//@param: id uint, authorityIds []string
//@return: err error

func (userService *UserService) SetUserAuthorities(adminAuthorityID, id uint, authorityIds []uint) (err error) {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		var user system.SysUser
		TxErr := tx.Where("id = ?", id).First(&user).Error
		if TxErr != nil {
			global.GVA_LOG.Debug(TxErr.Error())
			return errors.New("查询用户数据失败")
		}
		TxErr = tx.Delete(&[]system.SysUserAuthority{}, "sys_user_id = ?", id).Error
		if TxErr != nil {
			return TxErr
		}
		var useAuthority []system.SysUserAuthority
		for _, v := range authorityIds {
			e := AuthorityServiceApp.CheckAuthorityIDAuth(adminAuthorityID, v)
			if e != nil {
				return e
			}
			useAuthority = append(useAuthority, system.SysUserAuthority{
				SysUserId: id, SysAuthorityAuthorityId: v,
			})
		}
		TxErr = tx.Create(&useAuthority).Error
		if TxErr != nil {
			return TxErr
		}
		TxErr = tx.Model(&user).Update("authority_id", authorityIds[0]).Error
		if TxErr != nil {
			return TxErr
		}
		// 返回 nil 提交事务
		return nil
	})
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: DeleteUser
//@description: 删除用户
//@param: id float64
//@return: err error

func (userService *UserService) DeleteUser(id int) (err error) {
	return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Where("id = ?", id).Delete(&system.SysUser{}).Error; err != nil {
			return err
		}
		if err := tx.Delete(&[]system.SysUserAuthority{}, "sys_user_id = ?", id).Error; err != nil {
			return err
		}
		return nil
	})
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: SetUserInfo
//@description: 设置用户信息
//@param: reqUser model.SysUser
//@return: err error, user model.SysUser

func (userService *UserService) SetUserInfo(req system.SysUser) error {
	var user system.SysUser

	// 检查手机号是否已被其他用户使用（如果提供了手机号）
	if req.Phone != "" {
		if err := global.GVA_DB.Where("phone = ? AND id != ?", req.Phone, req.ID).First(&user).Error; err == nil {
			return errors.New("手机号已被其他用户使用")
		}
	}

	// 检查邮箱是否已被其他用户使用（如果提供了邮箱）
	if req.Email != "" {
		if err := global.GVA_DB.Where("email = ? AND id != ?", req.Email, req.ID).First(&user).Error; err == nil {
			return errors.New("邮箱已被其他用户使用")
		}
	}

	// 先获取用户的UUID，用于后续清除缓存
	if err := global.GVA_DB.Select("uuid").Where("id = ?", req.ID).First(&user).Error; err != nil {
		global.GVA_LOG.Warn("获取用户UUID失败", zap.Error(err), zap.Uint("userId", req.ID))
	}

	// 更新用户信息
	err := global.GVA_DB.Model(&system.SysUser{}).
		Select("updated_at", "nick_name", "header_img", "phone", "email", "enable", "grade", "school", "major", "education", "signature", "gender", "age").
		Where("id=?", req.ID).
		Updates(map[string]interface{}{
			"updated_at": time.Now(),
			"nick_name":  req.NickName,
			"header_img": req.HeaderImg,
			"phone":      req.Phone,
			"email":      req.Email,
			"enable":     req.Enable,
			"grade":      req.Grade,
			"school":     req.School,
			"major":      req.Major,
			"education":  req.Education,
			"signature":  req.Signature,
			"gender":     req.Gender,
			"age":        req.Age,
		}).Error

	// 清除用户信息缓存
	if err == nil && global.GVA_REDIS != nil && user.UUID.String() != "" {
		uuidStr := user.UUID.String()
		cacheKey := fmt.Sprintf("user:info:%s", uuidStr)
		if delErr := global.GVA_REDIS.Del(context.Background(), cacheKey).Err(); delErr != nil {
			global.GVA_LOG.Warn("清除用户信息缓存失败", zap.Error(delErr), zap.String("uuid", uuidStr))
		} else {
			global.GVA_LOG.Info("成功清除用户信息缓存", zap.String("uuid", uuidStr))
		}
	}

	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: SetSelfInfo
//@description: 设置用户信息
//@param: reqUser model.SysUser
//@return: err error, user model.SysUser

// 在 SetSelfInfo 方法中添加专业变更限制
func (userService *UserService) SetSelfInfo(req system.SysUser) error {
	var user system.SysUser

	// 1. 新增字段格式验证
	if req.Phone != "" && !utils.IsValidPhone(req.Phone) {
		return errors.New("手机号格式不正确")
	}

	if req.Email != "" && !utils.IsValidEmail(req.Email) {
		return errors.New("邮箱格式不正确")
	}

	// 2. 原有逻辑...
	// 检查手机号是否已被其他用户使用
	if req.Phone != "" {
		if err := global.GVA_DB.Where("phone = ? AND id != ?", req.Phone, req.ID).First(&user).Error; err == nil {
			return errors.New("手机号已被其他用户使用")
		}
	}

	// 检查邮箱是否已被其他用户使用
	if req.Email != "" {
		if err := global.GVA_DB.Where("email = ? AND id != ?", req.Email, req.ID).First(&user).Error; err == nil {
			return errors.New("邮箱已被其他用户使用")
		}
	}

	// 获取用户当前信息，检查专业和学校是否变更
	if err := global.GVA_DB.Select("major", "school", "auth_status").Where("id = ?", req.ID).First(&user).Error; err != nil {
		return err
	}

	// 检查用户是否已经完成专业认证，如果已认证则限制更改专业
	if (user.AuthStatus&int8(global.AuthStatusMajor)) != 0 && user.Major != req.Major && req.Major != 0 {
		return errors.New("您已完成专业认证，不可更改专业")
	}

	global.GVA_LOG.Info("SetSelfInfo update im")

	// 用户修改信息同步到openim
	imUser := request.IMUser{
		UserID:   strconv.FormatUint(uint64(req.ID), 10),
		NickName: req.NickName,
		FaceURL:  req.HeaderImg,
		Ex:       "",
	}
	if errUpdate := im.IMUserServiceApp.UpdateUserInfo(context.Background(), imUser); errUpdate != nil {
		global.GVA_LOG.Error("update im user_info failed!")
		return fmt.Errorf("update im user_info failed! %w", errUpdate)
	}
	global.GVA_LOG.Info("SetSelfInfo update im success!")

	// 创建更新映射
	updates := make(map[string]interface{})
	updates["updated_at"] = time.Now()
	updates["nick_name"] = req.NickName
	updates["header_img"] = req.HeaderImg
	updates["phone"] = req.Phone
	updates["email"] = req.Email
	updates["grade"] = req.Grade
	updates["school"] = req.School
	updates["education"] = req.Education
	updates["signature"] = req.Signature
	updates["gender"] = req.Gender
	updates["age"] = req.Age

	//// 如果需要更新认证状态
	//if needUpdateAuth {
	//	updates["auth_status"] = user.AuthStatus
	//}
	global.GVA_LOG.Info("SetSelfInfo pack updates", zap.Any("info", updates))

	// 更新用户信息
	err := global.GVA_DB.Model(&system.SysUser{}).
		Where("id=?", req.ID).
		Updates(updates).Error

	return err
}

// ClearRedisUserInfo 清除用户信息缓存
func (userService *UserService) ClearRedisUserInfo(uuid uuid.UUID) error {
	uuidStr := uuid.String()
	global.GVA_LOG.Info("开始清除用户信息缓存", zap.String("uuid", uuidStr))
	if global.GVA_REDIS != nil && uuidStr != "" {
		cacheKey := fmt.Sprintf("user:info:%s", uuidStr)
		if delErr := global.GVA_REDIS.Del(context.Background(), cacheKey).Err(); delErr != nil {
			global.GVA_LOG.Warn("清除用户信息缓存失败", zap.Error(delErr), zap.String("uuid", uuidStr))
			return delErr
		} else {
			global.GVA_LOG.Info("成功清除用户信息缓存", zap.String("uuid", uuidStr))
		}
	}
	return nil
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: SetSelfSetting
//@description: 设置用户配置
//@param: req datatypes.JSON, uid uint
//@return: err error

func (userService *UserService) SetSelfSetting(req common.JSONMap, uid uint) error {
	return global.GVA_DB.Model(&system.SysUser{}).Where("id = ?", uid).Update("origin_setting", req).Error
}

//@author: [piexlmax](https://github.com/piexlmax)
//@author: [SliverHorn](https://github.com/SliverHorn)
//@function: GetUserInfo
//@description: 获取用户信息
//@param: uuid uuid.UUID
//@return: err error, user system.SysUser

func (userService *UserService) GetUserInfo(uuid uuid.UUID) (user system.SysUser, err error) {
	var reqUser system.SysUser
	err = global.GVA_DB.First(&reqUser, "uuid = ?", uuid).Error
	if err != nil {
		return reqUser, err
	}
	return reqUser, err
}

//@author: [SliverHorn](https://github.com/SliverHorn)
//@function: FindUserById
//@description: 通过id获取用户信息
//@param: id int
//@return: err error, user *model.SysUser

func (userService *UserService) FindUserById(id int) (user *system.SysUser, err error) {
	var u system.SysUser
	err = global.GVA_DB.Where("id = ?", id).First(&u).Error
	return &u, err
}

// @author: [SliverHorn](https://github.com/SliverHorn)
// @function: FindUserByUuid
// @description: 通过uuid获取用户信息
// @param: uuid string
// @return: err error, user *model.SysUser
func (userService *UserService) FindUserByUuid(uuid string) (user *system.SysUser, err error) {
	var u system.SysUser
	if err = global.GVA_DB.Where("uuid = ?", uuid).First(&u).Error; err != nil {
		return &u, errors.New("用户不存在")
	}
	return &u, nil
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: ResetPassword
//@description: 修改用户密码
//@param: ID uint
//@return: err error

func (userService *UserService) ResetPassword(ID uint, password string) (err error) {
	err = global.GVA_DB.Model(&system.SysUser{}).Where("id = ?", ID).Update("password", utils.BcryptHash(password)).Error
	return err
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: GetUserInfoWithDict
//@description: 通过uuid获取用户信息并包含字典名称
//@param: uuid uuid.UUID
//@return: err error, user systemRes.SysUserWithDict

// 在 GetUserInfoWithDict 方法中增强错误处理
func (userService *UserService) GetUserInfoWithDict(uuid uuid.UUID) (user systemRes.SysUserWithDict, err error) {

	// 建议添加缓存逻辑
	// 1. 添加Redis客户端检查
	getUserInfoCacheKey := fmt.Sprintf("user:info:%s", uuid.String())

	// 2. 只有当Redis客户端初始化后才使用缓存
	if global.GVA_REDIS != nil {
		// 修改：使用JSON序列化和反序列化
		var userInfoJSON string
		if err := global.GVA_REDIS.Get(context.Background(), getUserInfoCacheKey).Scan(&userInfoJSON); err == nil {
			// 从JSON字符串解析到结构体
			if err := json.Unmarshal([]byte(userInfoJSON), &user); err == nil {
				return user, nil
			} else {
				global.GVA_LOG.Warn("解析用户缓存信息失败", zap.Error(err))
			}
		}
	}

	var reqUser system.SysUser
	err = global.GVA_DB.First(&reqUser, "uuid = ?", uuid).Error
	if err != nil {
		return user, err
	}

	// 获取字典名称，增加错误日志记录
	gradeName, gradeErr := userService.getDictionaryName(global.DictionaryGrade, uint(reqUser.Grade))
	if gradeErr != nil {
		global.GVA_LOG.Warn("获取年级名称失败", zap.Error(gradeErr), zap.Uint("gradeId", uint(reqUser.Grade)))
	}

	// 构建学校信息嵌套结构
	schoolName, schoolErr := userService.getDictionaryName(global.DictionarySchool, uint(reqUser.School))
	if schoolErr != nil {
		global.GVA_LOG.Warn("获取学校名称失败", zap.Error(schoolErr), zap.Uint("schoolId", uint(reqUser.School)))
	}
	schoolInfo := systemRes.SchoolInfo{
		ID:   reqUser.School,
		Name: schoolName,
	}

	// 构建专业信息嵌套结构
	majorName, majorErr := userService.getDictionaryNameById(global.DictionaryMajor, uint(reqUser.Major))
	if majorErr != nil {
		global.GVA_LOG.Warn("获取专业名称失败", zap.Error(majorErr), zap.Uint("majorId", uint(reqUser.Major)))
	}
	majorInfo := systemRes.MajorInfo{
		ID:   reqUser.Major,
		Name: majorName,
	}

	educationName, eduErr := userService.getDictionaryName(global.DictionaryEducation, uint(reqUser.Education))
	if eduErr != nil {
		global.GVA_LOG.Warn("获取学历名称失败", zap.Error(eduErr), zap.Uint("educationId", uint(reqUser.Education)))
	}

	// 获取性别名称
	genderName, genderErr := userService.getDictionaryName(global.DictionaryGender, uint(reqUser.Gender))
	if genderErr != nil {
		global.GVA_LOG.Warn("获取性别名称失败", zap.Error(genderErr), zap.Uint("genderId", uint(reqUser.Gender)))
	}

	// 查询用户最新的登录记录以获取省份信息
	var loginRecord system.SysLoginRecord
	loginErr := global.GVA_DB.Where("user_id = ?", reqUser.ID).Order("login_at DESC").First(&loginRecord).Error
	if loginErr != nil && !errors.Is(loginErr, gorm.ErrRecordNotFound) {
		global.GVA_LOG.Warn("获取登录记录失败", zap.Error(loginErr), zap.Uint("userId", reqUser.ID))
	}

	// 封装用户信息
	user = systemRes.SysUserWithDict{
		SysUser:       reqUser,
		GradeName:     gradeName,
		School:        schoolInfo,
		Major:         majorInfo,
		EducationName: educationName,
		Province:      loginRecord.Province, // 添加省份信息
		GenderName:    genderName,
	}

	// 存入缓存
	// 只有当Redis客户端初始化后才设置缓存
	if global.GVA_REDIS != nil {
		// 修改：将结构体转换为JSON字符串
		userInfoJSON, err := json.Marshal(user)
		if err != nil {
			global.GVA_LOG.Warn("序列化用户信息失败", zap.Error(err))
		} else {
			if err := global.GVA_REDIS.Set(context.Background(), getUserInfoCacheKey, string(userInfoJSON), time.Hour*24).Err(); err != nil {
				global.GVA_LOG.Warn("设置用户信息缓存失败", zap.Error(err))
			}
		}
	}

	return user, nil
}

// getDictionaryName 根据字典ID和值获取字典名称
func (userService *UserService) getDictionaryName(dictionaryID global.Dictionary, value uint) (string, error) {
	if value == 0 {
		return "", nil
	}

	var detail system.SysDictionaryDetail
	err := global.GVA_DB.Where("sys_dictionary_id = ? AND value = ?", dictionaryID, value).First(&detail).Error
	if err != nil {
		return "", err
	}
	// 处理专业名称中的括号备注信息
	label := detail.Label
	if idx := strings.Index(label, "("); idx > 0 {
		label = label[:idx]
	}

	return label, nil
}

// getDictionaryName id 获取字典名称
func (userService *UserService) getDictionaryNameById(dictionaryID global.Dictionary, id uint) (string, error) {
	if id == 0 {
		return "", nil
	}

	var detail system.SysDictionaryDetail
	err := global.GVA_DB.Where("id = ?", id).First(&detail).Error
	if err != nil {
		return "", err
	}
	if detail.SysDictionaryID != int(dictionaryID) {
		return "", errors.New("get dictionaryID failed")
	}
	return detail.Label, nil
}

// c端用户专用接口
func (userService *UserService) GetUserInfoListForC(info systemReq.GetUserList) (list interface{}, total int64, err error) {
	db := global.GVA_DB.Model(&system.SysUser{})
	var userList []system.SysUser
	// 1. 在 SysUser 表中查询 IDs 列表中的用户
	db = db.Where("id IN (?)", info.UserIds)
	if info.NickName != "" {
		db = db.Where("nick_name LIKE ?", "%"+info.NickName+"%")
	}
	if info.Phone != "" {
		db = db.Where("phone LIKE ?", "%"+info.Phone+"%")
	}
	if info.Username != "" {
		db = db.Where("username LIKE ?", "%"+info.Username+"%")
	}
	if info.Email != "" {
		db = db.Where("email LIKE ?", "%"+info.Email+"%")
	}
	if info.Grade != 0 {
		db = db.Where("grade = ?", info.Grade)
	}
	if info.School != 0 {
		db = db.Where("school = ?", info.School)
	}
	if info.Major != 0 {
		db = db.Where("major = ?", info.Major)
	}
	if info.Education != 0 {
		db = db.Where("education = ?", info.Education)
	}

	err = db.Count(&total).Error
	if err != nil {
		return
	}
	// 查询原始用户列表
	err = db.Preload("Authorities").Preload("Authority").Find(&userList).Error
	if err != nil {
		return
	}

	// 转换为包含嵌套对象的用户列表
	var userWithDictList []systemRes.SysUserWithDict
	for _, user := range userList {
		// 获取字典名称
		gradeName, _ := userService.getDictionaryName(global.DictionaryGrade, uint(user.Grade))
		// 构建学校信息嵌套结构
		schoolName, _ := userService.getDictionaryName(global.DictionarySchool, uint(user.School))
		schoolInfo := systemRes.SchoolInfo{
			ID:   user.School,
			Name: schoolName,
		}
		// 构建专业信息嵌套结构
		majorName, _ := userService.getDictionaryName(global.DictionaryMajor, uint(user.Major))
		majorInfo := systemRes.MajorInfo{
			ID:   user.Major,
			Name: majorName,
		}
		educationName, _ := userService.getDictionaryName(global.DictionaryEducation, uint(user.Education))

		// 封装用户信息
		userWithDict := systemRes.SysUserWithDict{
			SysUser:       user,
			GradeName:     gradeName,
			School:        schoolInfo,
			Major:         majorInfo,
			EducationName: educationName,
			Province:      "", // 列表接口不返回省份信息
		}
		userWithDictList = append(userWithDictList, userWithDict)
	}

	return userWithDictList, total, nil
}

//@author: [piexlmax](https://github.com/piexlmax)
//@function: MajorAuth
//@description: 用户专业认证
//@param: userID uint, majorID int
//@return: err error

// MajorAuth 用户专业认证
func (userService *UserService) MajorAuth(userID uint, majorID int) error {
	var user system.SysUser

	// 查询用户当前信息
	if err := global.GVA_DB.Select("major", "auth_status").Where("id = ?", userID).First(&user).Error; err != nil {
		global.GVA_LOG.Error("查询用户信息失败", zap.Error(err), zap.Uint("userId", userID))
		return err
	}

	// 检查用户是否已经完成专业认证，如果已认证则返回错误
	if (user.AuthStatus & int8(global.AuthStatusMajor)) != 0 {
		global.GVA_LOG.Info("用户已完成专业认证，暂不支持二次认证", zap.Uint("userId", userID))
		return errors.New("您已完成专业认证，暂不支持二次认证")
	}

	// 验证专业ID是否存在且为三级ID
	// 1. 专业字典ID为9
	const majorDictionaryID = 9

	// 2. 查询专业ID是否存在
	var detail system.SysDictionaryDetail
	err := global.GVA_DB.Where("id = ? AND sys_dictionary_id = ?", majorID, majorDictionaryID).First(&detail).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			global.GVA_LOG.Info("专业ID不存在", zap.Int("majorId", majorID))
			return errors.New("专业ID不存在")
		}
		global.GVA_LOG.Error("查询专业信息失败", zap.Error(err), zap.Int("majorId", majorID))
		return err
	}

	// 3. 检查是否为三级ID（判断该ID是否有子节点，有则不是三级ID）
	var count int64
	err = global.GVA_DB.Model(&system.SysDictionaryDetail{}).
		Where("parent_id = ? AND sys_dictionary_id = ?", majorID, majorDictionaryID).
		Count(&count).Error
	if err != nil {
		global.GVA_LOG.Error("查询专业子节点失败", zap.Error(err), zap.Int("majorId", majorID))
		return err
	}
	if count > 0 {
		global.GVA_LOG.Info("专业ID不是三级ID", zap.Int("majorId", majorID))
		return errors.New("请选择到最末级专业")
	}

	// 检查专业是否不同
	if user.Major != majorID {
		// 创建更新映射
		updates := make(map[string]interface{})
		updates["updated_at"] = time.Now()
		updates["major"] = majorID

		// 设置专业认证状态
		user.AuthStatus |= int8(global.AuthStatusMajor)
		updates["auth_status"] = user.AuthStatus

		if err := global.GVA_DB.Model(&system.SysUser{}).
			Where("id=?", userID).
			Updates(updates).Error; err != nil {
			global.GVA_LOG.Error("更新用户专业和认证状态失败", zap.Error(err), zap.Uint("userId", userID), zap.Int("majorId", majorID))
			return err
		}

		global.GVA_LOG.Info("用户专业认证成功", zap.Uint("userId", userID), zap.Int("oldMajor", user.Major), zap.Int("newMajor", majorID))
	} else {
		// 专业未变更，但仍需确保认证状态为已认证
		if (user.AuthStatus & int8(global.AuthStatusMajor)) == 0 {
			user.AuthStatus |= int8(global.AuthStatusMajor)
			if err := global.GVA_DB.Model(&system.SysUser{}).
				Where("id=?", userID).
				Update("auth_status", user.AuthStatus).Error; err != nil {
				global.GVA_LOG.Error("更新用户认证状态失败", zap.Error(err), zap.Uint("userId", userID))
				return err
			}

			global.GVA_LOG.Info("用户专业未变更，仅更新认证状态", zap.Uint("userId", userID), zap.Int("majorId", majorID))
		}
	}

	return nil
}

// GetUserByID 根据用户ID获取用户信息
func (userService *UserService) GetUserByID(userID uint) (system.SysUser, error) {
	var user system.SysUser
	err := global.GVA_DB.Where("id = ?", userID).First(&user).Error
	return user, err
}

// CheckUserMajorAuthStatus 检查用户是否已完成专业认证
func (userService *UserService) CheckUserMajorAuthStatus(userID uint) (bool, error) {
	user, err := userService.GetUserByID(userID)
	if err != nil {
		return false, err
	}
	// 检查专业认证状态（使用按位与操作检查第三位是否为1）
	return (user.AuthStatus & int8(global.AuthStatusMajor)) != 0, nil
}

// GetProfessionalNameByID 根据专业ID获取专业名称
func (userService *UserService) GetProfessionalNameByID(professionalID int) string {
	// 检查专业ID是否有效
	if professionalID <= 0 {
		return ""
	}
	// 查询专业信息
	var detail system.SysDictionaryDetail
	err := global.GVA_DB.Where("id = ? AND sys_dictionary_id = ?", professionalID, global.DictionaryMajor).First(&detail).Error
	if err != nil {
		// 查询失败时记录日志但不影响程序运行
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			global.GVA_LOG.Error("查询专业信息失败", zap.Int("professionalID", professionalID), zap.Error(err))
		}
		return ""
	}

	// 处理专业名称中的括号备注信息
	label := detail.Label
	if idx := strings.Index(label, "("); idx > 0 {
		label = label[:idx]
	}

	return label
}

// 找到 GetUserInfoWithFollowStatusAndDict 方法并修改
// 该方法应该在系统的某个服务文件中，这里假设是在 userFollowService 中
